<!DOCTYPE HTML>
<!--
-- Copyright (c) 2012-2020 MIRACL UK Ltd.
--
-- This file is part of MIRACL Core
-- (see https://github.com/miracl/core).
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--     http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-->
<html>
<head>
<title>JavaScript Test Hash-To-Point</title>
</head>
<body>
<h1>JavaScript Hash-To-Curve-Point Test Vectors</h1>
<script type="text/javascript"src=./../../src/rand.js></script>
<script type="text/javascript"src=./../../src/share.js></script>
<script type="text/javascript"src=./../../src/rom_curve.js></script>
<script type="text/javascript"src=./../../src/rom_field.js></script>
<script type="text/javascript"src=./../../src/uint64.js></script>
<script type="text/javascript"src=./../../src/aes.js></script>
<script type="text/javascript"src=./../../src/gcm.js></script>
<script type="text/javascript"src=./../../src/big.js></script>
<script type="text/javascript"src=./../../src/hmac.js></script>
<script type="text/javascript"src=./../../src/hash256.js></script>
<script type="text/javascript"src=./../../src/hash384.js></script>
<script type="text/javascript"src=./../../src/hash512.js></script>
<script type="text/javascript"src=./../../src/sha3.js></script>
<script type="text/javascript"src=./../../src/fp.js></script>
<script type="text/javascript"src=./../../src/ecp.js></script>
<script type="text/javascript"src=./../../src/nhs.js></script>
<script type="text/javascript"src=./../../src/ecdh.js></script>
<script type="text/javascript"src=./../../src/hpke.js></script>
<script type="text/javascript"src=./../../src/ctx.js></script>

<script type="text/javascript"src=./../../src/fp2.js></script>
<script type="text/javascript"src=./../../src/fp4.js></script>
<script type="text/javascript"src=./../../src/fp12.js></script>
<script type="text/javascript"src=./../../src/ecp2.js></script>
<script type="text/javascript"src=./../../src/pair.js></script>
<script type="text/javascript"src=./../../src/mpin.js></script>
<script type="text/javascript"src=./../../src/bls.js></script>

<p><a id="myLink4" href="#" onclick="ED25519();">ED25519 Hash to Point</a></p>
<p><a id="myLink4" href="#" onclick="C25519();">C25519 Hash to Point</a></p>
<p><a id="myLink5" href="#" onclick="NIST256();">NIST256 Hash to Point</a></p>
<p><a id="myLink6" href="#" onclick="GOLDILOCKS();">GOLDILOCKS Hash to Point</a></p>
<p><a id="myLink7" href="#" onclick="SECP256K1();">SECP256K1 Hash to Point</a></p>
<p><a id="myLink8" href="#" onclick="BLS12381();">BLS12381_G1 Hash to Point</a></p>
<p><a id="myLink9" href="#" onclick="BLS12381_G2();">BLS12381_G2 Hash to Point</a></p>

<script>

/* Test HTP */

function ceil(a,b) {
	return Math.floor(((a)-1)/(b)+1);
}

function asciitobytes(s) {
    var b = [],i;
    for (i = 0; i < s.length; i++) {
        b.push(s.charCodeAt(i));
    }
    return b;
}

function hash_to_field(ctx,hash,hlen,DST,M,ctr) {
	var u=[];
    var q=new ctx.BIG(0);
	q.rcopy(ctx.ROM_FIELD.Modulus);
    var k=q.nbits();
    var r=new ctx.BIG(0);
	r.rcopy(ctx.ROM_CURVE.CURVE_Order);
    var m=r.nbits();
    var L=ceil(k+ceil(m,2),8);
    var OKM = ctx.HMAC.XMD_Expand(hash,hlen,L*ctr,DST,M);
    var fd = []; 
    for (var i=0;i<ctr;i++)
    {
        for (var j=0;j<L;j++)
            fd[j]=OKM[i*L+j];
        var dx=ctx.DBIG.fromBytes(fd);
        var w=new ctx.FP(dx.mod(q));
        u[i]=new ctx.FP(w);
    }
    return u;
}

function htp(mywindow,ctx,mess,ro,nu,hlen) {
    var DSTRO = asciitobytes(ro);
    var DSTNU = asciitobytes(nu);
    var M = asciitobytes(mess);
	var u,P,P1;

	if (ctx.ECP.CURVETYPE != ctx.ECP.MONTGOMERY)
	{
		mywindow.document.write("Random oracle - message= "+mess+"<br>");

	    u=hash_to_field(ctx,ctx.HMAC.MC_SHA2,hlen,DSTRO,M,2);
		mywindow.document.write("u[0]= "+u[0].toString()+"<br>");
		mywindow.document.write("u[1]= "+u[1].toString()+"<br>");

		P=ctx.ECP.map2point(u[0]);
		mywindow.document.write("Q[0]= "+P.toString()+"<br>");
		P1=ctx.ECP.map2point(u[1]);
		mywindow.document.write("Q[1]= "+P1.toString()+"<br>");
		P.add(P1);
		P.cfp();
		P.affine();
		mywindow.document.write("P= "+P.toString()+"<br>");
	}
    mywindow.document.write("\nNon-Uniform"+"<br>");
    u=hash_to_field(ctx,ctx.HMAC.MC_SHA2,hlen,DSTNU,M,1);
    mywindow.document.write("u[0]= "+u[0].toString()+"<br>");
    P=ctx.ECP.map2point(u[0]);
    mywindow.document.write("Q= "+P.toString()+"<br>");
    P.cfp();
    P.affine();
    mywindow.document.write("P= "+P.toString()+"<br>");
}


function hash_to_field2(ctx,hash,hlen,DST,M,ctr) {
	var u=[];
    var q=new ctx.BIG(0);
	q.rcopy(ctx.ROM_FIELD.Modulus);
    var k=q.nbits();
    var r=new ctx.BIG(0);
	r.rcopy(ctx.ROM_CURVE.CURVE_Order);
    var m=r.nbits();
    var L=ceil(k+ceil(m,2),8);
    var OKM = ctx.HMAC.XMD_Expand(hash,hlen,2*L*ctr,DST,M);
    var fd = []; 
    for (var i=0;i<ctr;i++)
    {
        for (var j=0;j<L;j++)
            fd[j]=OKM[2*i*L+j];
        var dx=ctx.DBIG.fromBytes(fd);
        var w1=new ctx.FP(dx.mod(q));

        for (var j=0;j<L;j++)
            fd[j]=OKM[(2*i+1)*L+j];
        dx=ctx.DBIG.fromBytes(fd);
        var w2=new ctx.FP(dx.mod(q));

        u[i]=new ctx.FP2(w1,w2);
    }
    return u;
}

function htp2(mywindow,ctx,mess,ro,nu,hlen) {
    mywindow.document.write("Random oracle - message= "+mess+"<br>");
    var DSTRO = asciitobytes(ro);
    var DSTNU = asciitobytes(nu);
    var M = asciitobytes(mess);

    var u=hash_to_field2(ctx,ctx.HMAC.MC_SHA2,hlen,DSTRO,M,2);
    mywindow.document.write("u[0]= "+u[0].toString()+"<br>");
    mywindow.document.write("u[1]= "+u[1].toString()+"<br>");

    var P=ctx.ECP2.map2point(u[0]);
    mywindow.document.write("Q[0]= "+P.toString()+"<br>");
    var P1=ctx.ECP2.map2point(u[1]);
    mywindow.document.write("Q[1]= "+P1.toString()+"<br>");
    P.add(P1);
    P.cfp();
    P.affine();
    mywindow.document.write("P= "+P.toString()+"<br>");

    mywindow.document.write("\nNon-Uniform"+"<br>");
    u=hash_to_field2(ctx,ctx.HMAC.MC_SHA2,hlen,DSTNU,M,1);
    mywindow.document.write("u[0]= "+u[0].toString()+"<br>");
    P=ctx.ECP2.map2point(u[0]);
    mywindow.document.write("Q= "+P.toString()+"<br>");
    P.cfp();
    P.affine();
    mywindow.document.write("P= "+P.toString()+"<br>");
}


// ED25519 context
function ED25519() {
	var ctx = new CTX('ED25519');
	var ro="QUUX-V01-CS02-with-edwards25519_XMD:SHA-512_ELL2_RO_";
	var nu="QUUX-V01-CS02-with-edwards25519_XMD:SHA-512_ELL2_NU_";
	var hlen=64;//SHA512
	var mywindow=window.open();
    htp(mywindow,ctx,"",ro,nu,hlen);
    htp(mywindow,ctx,"abc",ro,nu,hlen);
    htp(mywindow,ctx,"abcdef0123456789",ro,nu,hlen);
    htp(mywindow,ctx,"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",ro,nu,hlen);
    htp(mywindow,ctx,"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",ro,nu,hlen);
}

// C25519 context
function C25519() {
	var ctx = new CTX('C25519');
	var ro="QUUX-V01-CS02-with-curve25519_XMD:SHA-512_ELL2_RO_";
	var nu="QUUX-V01-CS02-with-curve25519_XMD:SHA-512_ELL2_NU_";
	var hlen=64;//SHA512
	var mywindow=window.open();
    htp(mywindow,ctx,"",ro,nu,hlen);
    htp(mywindow,ctx,"abc",ro,nu,hlen);
    htp(mywindow,ctx,"abcdef0123456789",ro,nu,hlen);
    htp(mywindow,ctx,"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",ro,nu,hlen);
    htp(mywindow,ctx,"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",ro,nu,hlen);
}

// NIST256 context
function NIST256() {
	var ctx = new CTX('NIST256');
	var ro="QUUX-V01-CS02-with-P256_XMD:SHA-256_SSWU_RO_";
	var nu="QUUX-V01-CS02-with-P256_XMD:SHA-256_SSWU_NU_";
	var hlen=ctx.ECP.HASH_TYPE;
	var mywindow=window.open();
    htp(mywindow,ctx,"",ro,nu,hlen);
    htp(mywindow,ctx,"abc",ro,nu,hlen);
    htp(mywindow,ctx,"abcdef0123456789",ro,nu,hlen);
    htp(mywindow,ctx,"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",ro,nu,hlen);
    htp(mywindow,ctx,"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",ro,nu,hlen);
}

// GOLDILOCKS context
function GOLDILOCKS() {
	var ctx = new CTX('GOLDILOCKS');
	var ro="QUUX-V01-CS02-with-edwards448_XMD:SHA-512_ELL2_RO_";
	var nu="QUUX-V01-CS02-with-edwards448_XMD:SHA-512_ELL2_NU_";
	var hlen=ctx.ECP.HASH_TYPE;
	var mywindow=window.open();
    htp(mywindow,ctx,"",ro,nu,hlen);
    htp(mywindow,ctx,"abc",ro,nu,hlen);
    htp(mywindow,ctx,"abcdef0123456789",ro,nu,hlen);
    htp(mywindow,ctx,"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",ro,nu,hlen);
    htp(mywindow,ctx,"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",ro,nu,hlen);
}

// SECP256K1 context
function SECP256K1() {
	var ctx = new CTX('SECP256K1');
	var ro="QUUX-V01-CS02-with-secp256k1_XMD:SHA-256_SSWU_RO_";
	var nu="QUUX-V01-CS02-with-secp256k1_XMD:SHA-256_SSWU_NU_";
	var hlen=ctx.ECP.HASH_TYPE;
	var mywindow=window.open();
    htp(mywindow,ctx,"",ro,nu,hlen);
    htp(mywindow,ctx,"abc",ro,nu,hlen);
    htp(mywindow,ctx,"abcdef0123456789",ro,nu,hlen);
    htp(mywindow,ctx,"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",ro,nu,hlen);
    htp(mywindow,ctx,"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",ro,nu,hlen);
}

// BLS12381 context
function BLS12381() {
	var ctx = new CTX('BLS12381');
	var ro="QUUX-V01-CS02-with-BLS12381G1_XMD:SHA-256_SSWU_RO_";
	var nu="QUUX-V01-CS02-with-BLS12381G1_XMD:SHA-256_SSWU_NU_";
	var hlen=ctx.ECP.HASH_TYPE;
	var mywindow=window.open();
    htp(mywindow,ctx,"",ro,nu,hlen);
    htp(mywindow,ctx,"abc",ro,nu,hlen);
    htp(mywindow,ctx,"abcdef0123456789",ro,nu,hlen);
    htp(mywindow,ctx,"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",ro,nu,hlen);
    htp(mywindow,ctx,"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",ro,nu,hlen);
}

// BLS12381 context
function BLS12381_G2() {
	var ctx = new CTX('BLS12381');
	var ro="QUUX-V01-CS02-with-BLS12381G2_XMD:SHA-256_SSWU_RO_";
	var nu="QUUX-V01-CS02-with-BLS12381G2_XMD:SHA-256_SSWU_NU_";
	var hlen=ctx.ECP.HASH_TYPE;
	var mywindow=window.open();
    htp2(mywindow,ctx,"",ro,nu,hlen);
    htp2(mywindow,ctx,"abc",ro,nu,hlen);
    htp2(mywindow,ctx,"abcdef0123456789",ro,nu,hlen);
    htp2(mywindow,ctx,"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",ro,nu,hlen);
    htp2(mywindow,ctx,"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",ro,nu,hlen);
}

</script>
</body>
</html>
